package cn.mayday.algorithms.year2020.month12;

/**
 * 在一个 n * m 的二维数组中，每一行都按照从左到右递增的顺序排序，每一列都按照从上到下递增的顺序排序。
 * <p>
 * 请完成一个高效的函数，输入这样的一个二维数组和一个整数，判断数组中是否含有该整数。
 * <p>
 * 来源：力扣（LeetCode）
 * 链接：https://leetcode-cn.com/problems/er-wei-shu-zu-zhong-de-cha-zhao-lcof
 * 著作权归领扣网络所有。商业转载请联系官方授权，非商业转载请注明出处。
 * <p>
 * 现有矩阵 matrix 如下：
 * <p>
 * [
 * [1,   4,  7, 11, 15],
 * [2,   5,  8, 12, 19],
 * [3,   6,  9, 16, 22],
 * [10, 13, 14, 17, 24],
 * [18, 21, 23, 26, 30]
 * ]
 * <p>
 * 给定 target = 5，返回 true。
 * <p>
 * 给定 target = 20，返回 false。
 *
 * @author Mayday05
 * @date 2020/12/30 20:04
 */
public class Off04FindNumberIn2DArray {


    public static void main(String[] args) {
        int[][] matrix1 = {
                {1, 4, 7, 11, 15},
                {2, 5, 8, 12, 19},
                {3, 6, 9, 16, 22},
                {10, 13, 14, 17, 24},
                {18, 21, 23, 26, 30}
        };

        boolean result1 = new Off04FindNumberIn2DArray().findNumberIn2DArray(matrix1, 5);
        System.out.println("result1 === " + result1);

        boolean result2 = new Off04FindNumberIn2DArray().findNumberIn2DArray(matrix1, 20);
        System.out.println("result2 === " + result2);
    }

    // 方法一：暴力循环
    public boolean findNumberIn2DArray1(int[][] matrix, int target) {
        if (matrix == null || matrix.length == 0 || matrix[0].length == 0) {
            return false;
        }

        // 时间复杂度为O(m*n)
        int length = matrix.length;
        for (int i = 0; i < length; i++) {
            int high = matrix[i].length;
            for (int j = 0; j < high; j++) {
                int value = matrix[i][j];
                if (target == value) {
                    return true;
                }
            }
        }
        return false;
    }


    // 方法二：线性查找
    public boolean findNumberIn2DArray(int[][] matrix, int target) {
        if (matrix == null || matrix.length == 0 || matrix[0].length == 0) {
            return false;
        }

        // 时间复杂度为O(m+n), 想象下反方向旋转，成一个二叉树，根节点左边小，右边大,右上角开始遍历(或者左下角开始遍历都可以)
        int i = matrix.length - 1;
        int high = matrix[0].length; // 高度
        int j = 0;
        // 这里是右上角为标志位开始遍历
        while (i >= 0 && j < high) {
            int value = matrix[i][j];
            if (target == value) {
                return true;
            }
            if (value > target) {
                i--; // 右上角横向向左移动
            }
            if (value < target) {
                j++;
            }
        }
        return false;
    }

}
